/*
GEANT4 project of helium
*/

#include <memory>

#include "ActionInitialization.hh"
#include "DetectorConstruction.hh"
#include "G4RunManager.hh"
#include "G4RunManagerFactory.hh"
#include "G4ScoringManager.hh"
#include "G4Types.hh"
#include "G4UIExecutive.hh"
#include "G4UImanager.hh"
#include "G4VisExecutive.hh"
#include "MyMacros.hh"
#include "MyNpzScoreWriter.hh"
#include "PhysicsList.hh"
#include "Randomize.hh"

//#include "G4VUserPhysicsList.hh"

using std::unique_ptr, std::make_unique;

int main(int argc, char** argv)
{
    ///=================================== detect interactive mode (if no arguments) and define UI session
    //G4UIExecutive* ui = nullptr;
    unique_ptr<G4UIExecutive> ui;
    if (argc == 1) ui = make_unique<G4UIExecutive>(argc, argv);

    ////=================================== Set the Random engine
    const auto seed = (G4int)time(NULL);
    G4Random::setTheSeed(seed);
    LINFO("```[main] Initial seed = {}", seed);

    ///=================================== Construct the default run manager
    //  auto* runManager = G4RunManagerFactory::CreateRunManager();
    auto runManager = unique_ptr<G4RunManager>(G4RunManagerFactory::CreateRunManager());
#if 0
    G4int nThreads = std::min(G4Threading::G4GetNumberOfCores(), 4);
    runManager->SetNumberOfThreads(nThreads);
    LINFO("```[main] Geant4 threads number = {}", runManager->GetNumberOfThreads());
#endif

    ///=================================== Scoring manager
    auto* const scrMgr = G4ScoringManager::GetScoringManager();
    scrMgr->SetVerboseLevel(1);
    ///-------------------- 替换默认 writer, score 结果输出 npy 格式
    MyNpzScoreWriter* npyWriter = new MyNpzScoreWriter();
    scrMgr->SetScoreWriter(npyWriter);

    ///=================================== Detector construction
    DetectorConstruction* dtct = new DetectorConstruction();
    runManager->SetUserInitialization(dtct);

    ///=================================== Physics lists
    auto* const phyList = new PhysicsList();
    runManager->SetUserInitialization(phyList);

    ///=================================== User Action Initialization
    runManager->SetUserInitialization(new ActionInitialization(dtct));

    ///=================================== User Interface manager
    auto* const UImanager = G4UImanager::GetUIpointer();

    ///===================================
    if (ui)
    {
        ///-------------------------interactive mode; //initialize visualization
        auto visManager = make_unique<G4VisExecutive>();
        visManager->Initialize();
        UImanager->ApplyCommand("/control/execute init_vis.mac");
        ui->SessionStart();
    }
    else
    {
        ///------------------------- batch mode
        G4String command = "/control/execute ";
        G4String fileName = argv[1];
        UImanager->ApplyCommand(command + fileName);
    }
}

//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
